using System;
using System.Collections.Generic;

namespace XTengine.ComponentModel
{
    /// <summary>
    /// The component model base entity
    /// </summary>
    public class XTengineObject
    {
        public Dictionary<Type, IXTengineComponent> Components = new Dictionary<Type, IXTengineComponent>();

        public T AddComponent<T>() where T : IXTengineComponent
        {
            Type componentInterfaceType = typeof(T);

            return (T)AddComponent(componentInterfaceType);
        }

        public IXTengineComponent AddComponent(Type componentInterfaceType)
        {
            if (!componentInterfaceType.IsInterface)
                return null;

            Type componentClassType;
            bool componentExists = ComponentManager.ComponentTypeMap.TryGetValue(componentInterfaceType, out componentClassType);

            if (!componentExists)
                return null;

            object componentObject = Activator.CreateInstance(componentClassType);

            XTengineComponentBase newComponent = componentObject as XTengineComponentBase;
            IXTengineComponent componentInterface = newComponent as IXTengineComponent;

            if (newComponent != null)
            {
                newComponent.Site = this;

                Components[componentInterfaceType] = componentInterface;

                componentInterface.Attach();
            }

            return componentInterface;
        }

        public IXTengineComponent GetComponent(Type componentType)
        {
            if (!componentType.IsInterface)
                return null;

            IXTengineComponent component;
            Components.TryGetValue(componentType, out component);

            return component;
        }

        public T GetComponent<T>() where T : IXTengineComponent
        {
            IXTengineComponent component;
            Components.TryGetValue(typeof(T), out component);

            return (T)component;
        }

        public void RemoveComponent(IXTengineComponent component)
        {
            if (!this.Components.ContainsValue(component))
                return;

            Type foundType = null;
            foreach (KeyValuePair<Type, IXTengineComponent> pair in Components)
            {
                if (ReferenceEquals(component, pair.Value))
                {
                    foundType = pair.Key;
                    break;
                }
            }

            if (foundType != null)
                this.Components.Remove(foundType);

            component.Detach();

            (component as XTengineComponentBase).Site = null;
        }

        public void UpdateComponents()
        {
            foreach (KeyValuePair<Type, IXTengineComponent> pair in Components)
                pair.Value.Update();
        }
    }
}
